#include "vtor_i2c.h"

// 加入用户工程宏
#ifdef __DEMO_PROJECT__
#include "main.h"

VtorI2c vtorI2cSlaveArray[2] = {0};
VtorI2c* slaveI2c = NULL;

#define	I2C_SLAVE_SCL_GPIO_Port		GPIOB
#define I2C_SLAVE_SCL_Pin			GPIO_PIN_6
#define	I2C_SLAVE_SDA_GPIO_Port		GPIOB
#define I2C_SLAVE_SDA_Pin			GPIO_PIN_7

void VtorI2cSlave_WriteSda(VtorI2c* i2c, uint8_t level)
{
	if(i2c == slaveI2c)
	{
		HAL_GPIO_WritePin(I2C_SLAVE_SDA_GPIO_Port, I2C_SLAVE_SDA_Pin, level);
	}
}

uint8_t VtorI2cSlave_ReadScl(VtorI2c* i2c)
{
	if(i2c == slaveI2c)
	{
		return HAL_GPIO_ReadPin(I2C_SLAVE_SCL_GPIO_Port, I2C_SLAVE_SCL_Pin);
	}
	return 0;
}

uint8_t VtorI2cSlave_ReadSda(VtorI2c* i2c)
{
	if(i2c == slaveI2c)
	{
		return HAL_GPIO_ReadPin(I2C_SLAVE_SDA_GPIO_Port, I2C_SLAVE_SDA_Pin);
	}
	return 0;
}

void VtorI2cSlave_SetSdaDir(VtorI2c* i2c, uint8_t dir)
{
	if(i2c == slaveI2c)
	{
		GPIO_InitTypeDef GPIO_InitStruct = {0};
		GPIO_InitStruct.Pin = I2C_SLAVE_SDA_Pin;
		// 输出模式时，设置为开漏输出
		// 输入模式时，设置成边沿中断输入
		switch(dir)
		{
		case GPIO_DIR_OUTPUT:
			GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
			break;
		case GPIO_DIR_IT_2EDGE:
			GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
			break;
		default:
			GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
		}
		GPIO_InitStruct.Pull = GPIO_PULLUP;
		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
		HAL_GPIO_Init(I2C_SLAVE_SDA_GPIO_Port, &GPIO_InitStruct);
	}
}


void VtorI2cSlave_Init()
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};

	GPIO_InitStruct.Pull = GPIO_PULLUP;
	// cubemx初始化引脚时，需配置成input，因为slaveI2c指针还未初始化
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
	// 如果是在VtorI2cSlave_Init函数内，将其初始化为上升沿和下降沿中断
	GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;

	GPIO_InitStruct.Pin = I2C_SLAVE_SCL_Pin;
	HAL_GPIO_Init(I2C_SLAVE_SCL_GPIO_Port, &GPIO_InitStruct);

	GPIO_InitStruct.Pin = I2C_SLAVE_SDA_Pin;
	HAL_GPIO_Init(I2C_SLAVE_SDA_GPIO_Port, &GPIO_InitStruct);

	VtorI2c* i2c = &vtorI2cSlaveArray[0];
	i2c->selfDevAddr = 0x6a;
	// i2c->selfDevAddr = (0x50 << 1); // 从机i2c地址（包括读写bit）
	for(int i = 0; i < 10; i++)
	{
		//slaveI2c->regData[i] = 0xff;
		i2c->regData[i] = i % 10 + '0';
	}
	// 测试从机
    VtorI2cSlave_SetSdaDir(i2c, GPIO_DIR_IT_2EDGE);

	// 开启外部中断
	HAL_NVIC_SetPriority(EXTI9_5_IRQn, 3, 3);
	HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
	// 内部变量初始化完成后，再对指针进行赋值
	slaveI2c = i2c;
}

void VtorTimer_BufferI2cSlaveRxTask(void)
{
	// 将i2c收到的数据转发给uart
	uint8_t rxBuf[150] = {'\0'};
	
	if(VtorI2cSlave_ReadBuffer(slaveI2c, rxBuf, 150-1))
	{
		VtorDebugChanPrintf(rxBuf);
		//VtorString_ChanPrintBuffer(VTOR_PRINT_CHAN_UART1, rxBuf, rxBufLen);
	}
	VtorTimer_Stop(VtorTimer_BufferI2cSlaveRxTask);
}

void VtorI2cSlave_WriteRegCallback(VtorI2c* i2c)
{
	// 主机写了接收寄存器，那么从机启动接收任务
	if(i2c->regAddr == VTOR_I2C_REG_MOSI_BUF_LEN)
	{
		VtorTimer_Start(VtorTimer_BufferI2cSlaveRxTask, 0);
	}
	if(i2c->regAddr == VTOR_I2C_REG_MOSI_BIG_BUF)
	{
		//push i2c->serialRegister;
		i2c->regAddr--;
	}
	//VtorPrintf("reg write [%x]=%d\r\n", i2c->regAddr, i2c->regData[i2c->regAddr]);
}

void VtorI2cSlave_ReadRegCallback(VtorI2c* i2c)
{
	//VtorPrintf("reg read [%x]=%d\r\n", i2c->regAddr, i2c->regData[i2c->regAddr]);
	
	if(i2c->regAddr == VTOR_I2C_REG_MISO_BIG_BUF_CTRL)
	{
		uint8_t misoCtrl = VtorI2cMaster_GetBigBufferMimo(
			iapEepromData.newFile.fileSize - vtorIap.iapTotalRxCnt);
		i2c->regData[VTOR_I2C_REG_MISO_BIG_BUF_CTRL] = misoCtrl;
		i2c->serialRegister = misoCtrl;
	}
	if(i2c->regAddr == VTOR_I2C_REG_MISO_BIG_BUF)
	{
		//pop i2c->serialRegister;
		i2c->serialRegister = *(uint8_t*)(vtorIap.iapStartAddr + vtorIap.iapTotalRxCnt);
		vtorIap.iapTotalRxCnt++;
		i2c->regAddr--;
	}
}

// 在对应的中断处理函数内，写好正确的中断
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if (GPIO_Pin == I2C_SLAVE_SCL_Pin)
	{
		VtorI2cSlave_SclHandler(slaveI2c);
	}
	if (GPIO_Pin == I2C_SLAVE_SDA_Pin)
	{
		VtorI2cSlave_SdaHandler(slaveI2c);
	}
}

void EXTI9_5_IRQHandler(void)
{
	/* USER CODE BEGIN EXTI9_5_IRQn 0 */

	/* USER CODE END EXTI9_5_IRQn 0 */
	HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6);
	HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_7);
	/* USER CODE BEGIN EXTI9_5_IRQn 1 */

	/* USER CODE END EXTI9_5_IRQn 1 */
}

void VtorI2cSlave_StopCallback(VtorI2c* i2c)
{
	// 从机结束中断回调函数，设置标志位，等待返回数据
	if(i2c == slaveI2c)
	{
	}
}
#endif

